package com.niiwoo.civet.account.service.local.check.job.parse;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.concurrent.Callable;

import com.niiwoo.civet.account.service.local.check.job.api.ParseService;
import com.niiwoo.civet.account.service.local.check.job.check.TypeDispatcher;
import com.niiwoo.civet.account.service.local.check.job.enums.CheckFileTypeEnum;
import com.niiwoo.civet.account.service.local.check.job.properties.AccountCheckingProperties;
import com.niiwoo.civet.account.service.local.check.job.util.SpringApplicationContextHolder;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class AccountCheckingParseTask implements Callable<Boolean> {

	@SuppressWarnings("rawtypes")
	private ParseService parseService;

	private CheckFileTypeEnum checkFileType;

	private AccountCheckingProperties properties;
	
	@SuppressWarnings("rawtypes")
	private Class parseCls;

	private TypeDispatcher dispatcher;
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public AccountCheckingParseTask(CheckFileTypeEnum checkFileType, Class parseCls, TypeDispatcher dispatcher,
			AccountCheckingProperties properties) {
		this.checkFileType = checkFileType;
		this.parseCls = parseCls;
		this.parseService = (ParseService) SpringApplicationContextHolder.getBean(parseCls);
		this.dispatcher = dispatcher;
		this.properties = properties;
	}

	public InputStream getFileInputStream() throws FileNotFoundException {
		File file = new File(properties.getCheckFilePath(checkFileType.getCode()));
		
		if (!file.exists()) {
			return null;
		}

		return new FileInputStream(file);
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public Boolean call() throws Exception {
		// 如果是重新对账且必须删除重新来则先删除所有数据
		if (properties.isReloadData()) {
			try {
				parseService.deleteCheckRecord(properties.getCheckRecordId());
			} catch (Exception e1) {
				log.error("delete all detail before parse checkfile to db fail, checkfiletype[{}], ", checkFileType.getCode(), e1.getMessage(), e1);
				return false;
			}
		}
		
		BufferedReader br = null;
		InputStream is = null;
		String record;
		try {
			is = getFileInputStream();
			if (is == null) {
				return true;
			}
			
			dispatcher.registeDispatcher(parseCls.getName(), (ParseService) SpringApplicationContextHolder.getBean(parseCls));
			
			br = new BufferedReader(new InputStreamReader(is));

			boolean isFirstRecord = true;
			boolean hasRecord = false;
			Object obj;
			while ((record = br.readLine()) != null) {
				if (record == null || "".equals(record))
					continue;

				if (isFirstRecord && properties.isRemoveFirst()) {
					isFirstRecord = false;
					continue;
				}

				obj = parseService.parse(properties.getCheckRecordId(), record);

				if (obj == null)
					continue;
				
				if (!hasRecord) {
					hasRecord = true;
				}

				dispatcher.dispath(parseCls.getName(), obj);
			}

			dispatcher.notifyDone(parseCls.getName());
			
			// 执行扩展业务
			if (hasRecord) parseService.extendBusiness(properties.getCheckRecordId());
			return true;
		} catch (Exception e) {
			log.error("error checkfile[{}], {}", checkFileType.getCode(), e.getMessage(), e);
			try {
				parseService.deleteCheckRecord(properties.getCheckRecordId());
			} catch (Exception e1) {
				log.error("parse2db fail, checkfiletype[{}], ", checkFileType.getCode(), e1.getMessage(), e1);
			}
			return false;
		} finally {
			try {
				if (is != null) {
					is.close();
				}
				if (br != null) {
					br.close();
				}
			} catch (Exception e) {
			}
		}

	}
}
